﻿// MemoryTest.cpp: 定义应用程序的入口点。
//

#include "MemoryTest.h"
#include <windows.h>
#include <iostream>
#include <windows.h>
#include <iostream>
#include <TlHelp32.h>
#include <Psapi.h>
#include <windows.h>
#include <iostream>
#include <iostream>
#include <string>
#include <windows.h>
#include <locale>
#include <codecvt>
#include <iomanip>
#include <windows.h>
#include <iostream>
#include <vector>
#include <sstream>
#include <ranges>
#include <windows.h>
#include <psapi.h>
#include <iostream>
#include <vector>
#include <map>
#pragma comment(lib, "psapi.lib")  // 需要链接PSAPI库

using namespace std;
// 跨平台UTF-8输出函数
void print_utf8(const char8_t* str) {
#ifdef _WIN32
	// Windows平台：使用宽字符输出
	static bool initialized = []() {
		SetConsoleOutputCP(65001);
		return true;
	}();

	std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
	std::wcout << converter.from_bytes(reinterpret_cast<const char*>(str));
#else
	// Linux/macOS：直接输出UTF-8
	std::cout << reinterpret_cast<const char*>(str);
#endif
}

//// 使用示例
//int main() {
//	const char8_t* msg = u8"跨平台UTF-8输出";
//	print_utf8(msg);
//	return 0;
//}

void PrintProcessMemoryRegions(DWORD process_id) {
	HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
	if (process_handle == NULL) {
		std::cerr << "OpenProcess failed. Error: " << GetLastError() << std::endl;
		return;
	}

	// 当前查询的地址（从0开始）
	LPVOID address = 0;

	// 内存信息结构体
	MEMORY_BASIC_INFORMATION mbi;

	// 循环遍历所有内存区域
	while (VirtualQueryEx(process_handle, address, &mbi, sizeof(mbi))) {
		// 输出内存区域信息
		std::cout << "基址: 0x" << std::hex << mbi.BaseAddress
			<< ", 大小: " << std::dec << mbi.RegionSize / 1024 << " KB"
			<< ", 状态: ";

		switch (mbi.State) {
		case MEM_COMMIT: std::cout << "已提交"; break;
		case MEM_RESERVE: std::cout << "已保留"; break;
		case MEM_FREE: std::cout << "空闲"; break;
		default: std::cout << "未知"; break;
		}

		std::cout << ", 保护: ";

		if (mbi.Protect & PAGE_READONLY) std::cout << "只读 ";
		if (mbi.Protect & PAGE_READWRITE) std::cout << "读写 ";
		if (mbi.Protect & PAGE_EXECUTE) std::cout << "可执行 ";
		if (mbi.Protect & PAGE_NOACCESS) std::cout << "不可访问 ";

		std::cout << std::endl;

		// 移动到下一个内存区域
		address = (LPVOID)((DWORD64)mbi.BaseAddress + mbi.RegionSize);
	}
	CloseHandle(process_handle);
}


BOOL ReadProcessData(DWORD process_id, LPVOID address, LPVOID buffer, SIZE_T size) {
	HANDLE process_handle = OpenProcess(PROCESS_VM_READ, FALSE, process_id);
	if (process_handle == NULL) {
		return FALSE;
	}
	BOOL result = ReadProcessMemory(process_handle, address, buffer, size, NULL);

	if (!result) return result;

	HMODULE hModule[100] = { 0 };
	DWORD dwRet;
	EnumProcessModules(process_handle, hModule, sizeof(hModule), &dwRet);

	CloseHandle(process_handle);
	return result;
}


bool hasDebugPrivilege() {
	HANDLE hToken;
	TOKEN_PRIVILEGES tp;
	LUID luid;

	// 打开当前进程令牌
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		return false;
	}

	// 获取SE_DEBUG_NAME特权的LUID
	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
		CloseHandle(hToken);
		return false;
	}

	// 检查特权状态
	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	tp.Privileges[0].Attributes = 0;

	if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL)) {
		CloseHandle(hToken);
		return false;
	}

	DWORD error = GetLastError();
	CloseHandle(hToken);

	return (error == ERROR_NOT_ALL_ASSIGNED) ? false : true;
}

bool checkProcessAccess(DWORD process_id) {
	// 步骤1：尝试直接打开进程
	HANDLE process_handle = OpenProcess(
		PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
		FALSE,
		process_id
	);

	if (process_handle != NULL) {
		std::cout << "成功获取PROCESS_VM_READ访问权限" << std::endl;
		CloseHandle(process_handle);
		return true;
	}

	// 步骤2：分析错误码
	DWORD error = GetLastError();
	std::cerr << "无法获取访问权限。错误码: " << error << std::endl;

	// 步骤3：检查是否有SE_DEBUG_NAME特权
	bool hasDebugPriv = hasDebugPrivilege();
	std::cout << "SE_DEBUG_NAME特权状态: " << (hasDebugPriv ? "已启用" : "未启用") << std::endl;

	// 步骤4：检查进程完整性级别（是否为高完整性/管理员）
	bool isHighIntegrity = false;
	HANDLE hToken;
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
		DWORD tokenInfoLength = 0;
		GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &tokenInfoLength);

		PTOKEN_MANDATORY_LABEL pTokenIntegrity = (PTOKEN_MANDATORY_LABEL)LocalAlloc(0, tokenInfoLength);
		if (pTokenIntegrity && GetTokenInformation(hToken, TokenIntegrityLevel, pTokenIntegrity, tokenInfoLength, &tokenInfoLength)) {
			DWORD integrityLevel = *GetSidSubAuthority(pTokenIntegrity->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTokenIntegrity->Label.Sid) - 1));
			isHighIntegrity = (integrityLevel >= SECURITY_MANDATORY_HIGH_RID);
		}
		LocalFree(pTokenIntegrity);
		CloseHandle(hToken);
	}

	std::cout << "进程完整性级别: " << (isHighIntegrity ? "高（管理员）" : "中/低") << std::endl;

	return false;
}


// 读取进程内存（指定地址）
bool ReadProcessMemoryAtAddress(DWORD process_id, UINT64 address, void* buffer, SIZE_T size) {
	// 打开目标进程
	HANDLE process_handle = OpenProcess(
		PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
		FALSE,
		process_id
	);

	if (process_handle == NULL) {
		std::cerr << "OpenProcess failed. Error: " << GetLastError() << std::endl;
		return false;
	}

	// 查询内存区域信息
	MEMORY_BASIC_INFORMATION mbi = { 0 };
	if (!VirtualQueryEx(process_handle, (LPCVOID)address, &mbi, sizeof(mbi))) {
		std::cerr << "VirtualQueryEx failed. Error: " << GetLastError() << std::endl;
		CloseHandle(process_handle);
		return false;
	}

	// 检查内存区域是否可读
	if (!(mbi.Protect & (PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE))) {
		std::cerr << "Memory region is not readable." << std::endl;
		CloseHandle(process_handle);
		return false;
	}

	// 计算实际可读取的大小（避免越界）
	SIZE_T bytesToRead = min(size, (SIZE_T)((UINT64)mbi.BaseAddress + mbi.RegionSize - address));

	// 读取内存
	SIZE_T bytesRead = 0;
	BOOL result = ReadProcessMemory(
		process_handle,
		(LPCVOID)address,
		buffer,
		bytesToRead,
		&bytesRead
	);

	CloseHandle(process_handle);

	if (!result || bytesRead != bytesToRead) {
		std::cerr << "ReadProcessMemory failed. Error: " << GetLastError() << std::endl;
		return false;
	}

	return true;
}

// 示例：读取DWORD值
DWORD ReadDWORDFromProcess(DWORD process_id, UINT64 address) {
	DWORD value = 0;
	if (ReadProcessMemoryAtAddress(process_id, address, &value, sizeof(DWORD))) {
		return value;
	}
	return 0;
}

// 示例：读取字符串
std::string ReadStringFromProcess(DWORD process_id, UINT64 address, SIZE_T maxLength = 256) {
	std::vector<char> buffer(maxLength);
	if (ReadProcessMemoryAtAddress(process_id, address, buffer.data(), maxLength)) {
		return std::string(buffer.data());
	}
	return "";
}

std::vector<UINT64> ScanMemoryForValue(DWORD process_id, const void* value, SIZE_T size) {
	std::vector<UINT64> results;
	HANDLE process_handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_id);
	if (process_handle == NULL) {
		return results;
	}

	UINT64 address = 0;
	MEMORY_BASIC_INFORMATION mbi;

	// 遍历所有内存区域
	while (VirtualQueryEx(process_handle, (LPCVOID)address, &mbi, sizeof(mbi))) {
		// 只处理可读且已提交的内存
		if (mbi.State == MEM_COMMIT &&
			(mbi.Protect & (PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)) &&
			!(mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS))) {

			// 分配缓冲区并读取内存
			std::vector<BYTE> buffer(mbi.RegionSize);
			SIZE_T bytesRead = 0;

			if (ReadProcessMemory(process_handle, mbi.BaseAddress, buffer.data(), mbi.RegionSize, &bytesRead)) {
				// 在缓冲区中搜索值
				for (SIZE_T i = 0; i <= bytesRead - size; i++) {
					if (memcmp(buffer.data() + i, value, size) == 0) {
						results.push_back((UINT64)mbi.BaseAddress + i);
					}
				}
			}
		}
		// 移动到下一个内存区域
		address = (UINT64)mbi.BaseAddress + mbi.RegionSize;
	}

	CloseHandle(process_handle);
	return results;
}

void EnumProcessesByPSAPI() {
	// 定义足够大的数组存储进程ID
	DWORD processIds[1024];
	DWORD needed;

	// 获取所有进程ID
	if (!EnumProcesses(processIds, sizeof(processIds), &needed)) {
		std::cerr << "EnumProcesses failed: " << GetLastError() << std::endl;
		return;
	}

	// 计算进程数量
	DWORD processCount = needed / sizeof(DWORD);

	// 遍历每个进程
	for (DWORD i = 0; i < processCount; i++) {
		if (processIds[i] != 0) {
			HANDLE process_handle = OpenProcess(
				PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
				FALSE,
				processIds[i]
			);

			if (process_handle != NULL) {
				// 获取进程可执行文件路径
				wchar_t exePath[MAX_PATH];
				if (GetModuleFileNameExW(process_handle, NULL, exePath, MAX_PATH)) {
					std::wcout << L"进程ID: " << processIds[i]
						<< L", 路径: " << exePath << std::endl;
				}

				CloseHandle(process_handle);
			}
		}
	}
}


#include "./Scanner.hpp"
void pointer_chain(std::map<UINT64, std::vector<UINT64>>& map, const std::unique_ptr<Scanner>& scanner, UINT64 address) {
	if (map.contains(address)) {
		return;
	}
	auto results = scanner->search(&address, sizeof(address));
	map[address] = results;
	std::ostringstream oss;
	oss << "0x" << std::uppercase << std::hex << std::setw(16) << std::setfill('0') << address << ":" << std::endl;
	for (auto result : results) {
		oss << "0x" << std::uppercase << std::hex << std::setw(16) << std::setfill('0') << result << " ";
	}
	std::cout << oss.str() << std::endl << std::endl;

	for (auto result : results) {
		pointer_chain(map, scanner, result);
	}
}
int main() {
	std::map<UINT64, std::vector<UINT64>> map;
	auto scanner = std::make_unique<Scanner>(600);
	scanner->open();

	auto str = u8"How do you turn this on";//u8"沿见：[图片]";
	auto len = std::char_traits<char8_t>::length(str);
	auto results = ScanMemoryForValue(43828, str, len);
	std::ostringstream oss;
	oss << "leaves:" << std::endl;
	for (auto result : results) {
		oss << "0x" << std::uppercase << std::hex << std::setw(16) << std::setfill('0') << result << " ";
	}
	std::cout << oss.str() << std::endl << std::endl;

	map[0] = results;
	for (auto address : results) {
		pointer_chain(map, scanner, address);
	}

	scanner->close();

	//EnumProcessesByPSAPI();
	//const char8_t* a = u8"啊实打实大苏打东方v那就拿出就是你帮我";//u8"沿见：[图片]";
	//auto len = std::char_traits<char8_t>::length(str);
	//auto results = ScanMemoryForValue(600, str, len);

	//map[0] = results;
	//for (auto result : results) {
	//	pointer_chain(map, result);
	//}
	return 0;
	//std::ostringstream oss;
	//for (auto result : results) {
	//	oss << "0x" << std::uppercase << std::hex << std::setw(16) << std::setfill('0') << result << " ";
	//}
	//std::cout << oss.str() << std::endl << std::endl;

	//{
	//	//auto a = 0x000001A68ED1B060;
	//	auto a = 0x000001A687C1FD78;
	//	auto results = ScanMemoryForValue(600, &a, sizeof(a));
	//	std::ostringstream oss;
	//	for (auto result : results) {
	//		oss << "0x" << std::uppercase << std::hex << std::setw(16) << std::setfill('0') << result << " ";
	//	}
	//	std::cout << oss.str() << std::endl << std::endl;
	//}

	//PrintProcessMemoryRegions(600);
	// 600
	// 20588
	//DWORD targetProcessId = 1676; // 替换为目标进程ID
	//int gap = 0.5 * 1024 * 1024 / sizeof(int);
	//unsigned int minAddress = 0;// 2147370000;
	//unsigned int maxAddress = 0xFFFFFFFF - gap;
	//unsigned int targetAddress = minAddress;

	//int data = 0;
	//while (targetAddress < maxAddress) {
	//	auto result = ReadProcessData(targetProcessId, (LPVOID)targetAddress, &data, sizeof(data));
	//	auto a = int(100 * double(targetAddress - minAddress) / (maxAddress - minAddress));
	//	if (result) {
	//		std::cout << "(" << targetAddress << ")" << a << "%, Read data: " << data << std::endl;
	//		break;
	//	}
	//	else {
	//		std::cout << "(" << targetAddress << ")" << a << "%, Failed to read." << std::endl;
	//	}
	//	targetAddress += gap;
	//}
	//if (targetAddress >= maxAddress) {
	//	return 0;
	//}
	//auto right = targetAddress;
	//auto left = targetAddress - gap;

	//do {
	//	targetAddress = right - (right - left) / 2;
	//	auto result = ReadProcessData(targetProcessId, (LPVOID)targetAddress, &data, sizeof(data));
	//	if (result) {
	//		std::cout << left << "/" << right << "(" << targetAddress << ") Read data: " << data << std::endl;
	//	}
	//	else {
	//		std::cout << left << "/" << right << "(" << targetAddress << ") Failed to read." << std::endl;
	//	}
	//	if (result) {
	//		right = targetAddress - 1;
	//	}
	//	else {
	//		left = targetAddress;
	//	}

	//} while (left < right);


	//while (1) {
	//	auto result = ReadProcessData(targetProcessId, (LPVOID)targetAddress, &data, sizeof(data));
	//	if (result) {
	//		std::cout << targetAddress << ":" << data << std::endl;
	//	}
	//	else {
	//		std::cout << "end." << std::endl;
	//		break;
	//	}
	//	++targetAddress;
	//}
	//return 0;




	//// 替换为目标进程ID
	//DWORD targetPid = 600;
	//if (checkProcessAccess(targetPid)) {
	//    std::cout << "可以访问目标进程的内存" << std::endl;
	//}
	//else {
	//    std::cout << "无法访问目标进程的内存" << std::endl;
	//    std::cout << "建议: 尝试以管理员身份运行程序" << std::endl;
	//}
	//return 0;
	return 0;
}